<?php
/**
 * 分页类
 * 
 * @package SFramework
 * @author Shuky
 * @since v1.0
 * @version $Id: Paginator.php 90 2011-01-07 18:38:29Z shukyoo@gmail.com $
 */
namespace SF;

/**
 * 扩展接口
 * 如需自定义分页样式算法，则需要继承此接口
 */
interface PaginatorInterface
{
	public function getPages(Paginator $paginator);
}


/**
 * 分页
 */
class Paginator
{
	// 总条数
	protected $_itemCount = 0;
	// 总页数
	protected $_pageCount = 1;
	// 每页数
	protected $_perPage = 20;
	// 当前页
	protected $_curPage = 1;
	// 显示页数
	protected $_pageRange = 12;
	// 最终分页
	protected $_pages = null;


	public function __construct($page, $count, $perPage = null, $pageRange = null)
	{
		if ($perPage) {
			$this->setPerPage($perPage);
		}
		if ($pageRange) {
			$this->setPageRange($pageRange);
		}
		$this->_itemCount = (int)$count;
		$this->_curPage = ($page < 1) ? 1 : (int)$page;
		$this->_pageCount = ceil($count / $this->_perPage);
	}


	/**
	 * 获取分页
	 */
	public function getPages($pageStyle = null)
	{
		if (null === $this->_pages) {
			$this->_pages = $this->_createPages($pageStyle);
		}
		return $this->_pages;
	}


	/**
	 * 获取组织好的html代码分页，样式自定义
	 * 基本html分页样式，暂不作扩展，如有特殊页面显示需要可使用getPages自定义显示
	 * 这里使用到router
	 */
	public function getRender($url = '')
	{
		// 组织url
        if (!$url) {
            $url = \SF\Router::getInstance()->genQuery();
        }
        $part = explode('?', $url);
        if (isset($part[1])) {
            $part[1] = trim(preg_replace('/&?page=\d+/i', '', $part[1]), '&');
        }
        $url = $part[0] .'?'. (empty($part[1]) ? '' : $part[1].'&');

		// 组织html
        $html = '';
        if ($this->getPageCount() > 1) {
            $page = $this->getPages();
            $html = '<ul id="page">';
            if (isset($page->pre)) {
                $html .= '<li class="pre"><a href="'. $url .'page='. $page->pre .'">上一页</a></li>';
            }
            foreach ($page->ranges as $p) {
                $cur = ($p == $page->curPage) ? ' class="cur"' : '';
                $html .= '<li'. $cur .'><a href="'. $url .'page='. $p .'">'. $p .'</a></li>';
            }
            if (isset($page->next)) {
                $html .= '<li class="next"><a href="'. $url .'page='. $page->next .'">下一页</a></li>';
            }
            $html .= '</ul>';
        }

		return $html;
	}


	/**
	 * 创建分页
	 * @return object stdClass
	 */
	protected function _createPages($pageStyle = null)
	{
		$pages = new \stdClass();
		$pages->itemCount = $this->_itemCount;
		$pages->pageCount = $this->_pageCount;
		$pages->perPage = $this->_perPage;
		$pages->curPage = $this->_curPage;
		$pages->pageRange = $this->_pageRange;
		// 上一页
		if ($pages->curPage > 1) {
			$pages->pre = $this->_curPage - 1;
		}
		// 下一页
		if ($pages->curPage < $this->_pageCount) {
			$pages->next = $this->_curPage + 1;
		}
		// 分布
		$pages->ranges = $this->_loadPageStyle($pageStyle);
		$pages->rangeFirst = min($pages->ranges);
		$pages->rangeLast = max($pages->ranges);
		return $pages;
	}


	/**
	 * 加载分页样式
	 * 如无扩展算法，则加载默认分页算法
	 */
	protected function _loadPageStyle($pageStyle = null)
	{
		if ($pageStyle && $pageStyle instanceof PaginatorInterface) {
			return $pageStyle->getPages($this);
		} else {
			$pageRange = $this->getPageRange();
			$pageNumber = $this->getCurPage();
			$pageCount  = $this->getPageCount();
			if ($pageRange > $pageCount) {
				$pageRange = $pageCount;
			}
			$delta = ceil($pageRange / 2);
			if ($pageNumber - $delta > $pageCount - $pageRange) {
				$lowerBound = $pageCount - $pageRange + 1;
				$upperBound = $pageCount; 
			} else {
				if ($pageNumber - $delta < 0) {
					$delta = $pageNumber;
				}
				$offset     = $pageNumber - $delta;
				$lowerBound = $offset + 1; 
				$upperBound = $offset + $pageRange;
			}
			$pages = array();
			for ($i = $lowerBound; $i <= $upperBound; $i++) {
				$pages[] = $i;
			}
			return $pages;
		}
	}


	/**
	 * 获取类参数
	 */
	public function getItemCount()
	{
		return $this->_itemCount;
	}

	public function getPageCount()
	{
		return $this->_pageCount;
	}

	public function getPerPage()
	{
		return $this->_perPage;
	}

	public function getCurPage()
	{
		return $this->_curPage;
	}

	public function getPageRange()
	{
		return $this->_pageRange;
	}


	/**
	 * 设置类参数
	 */
	public function setPerPage($perPage)
	{
		$this->_perPage = (int)$perPage;
	}

	public function setPageRange($pageRange)
	{
		$this->_pageRange = (int)$pageRange;
	}
}